#include <cstdio>
#include <algorithm>
using namespace std;
const int N=1e6+50;
int n,k;
int v[N],ans_min[N],ans_max[N];
//数组模拟队列
int head,tail;
int que[N];
int pos[N];
void get_min(){
    head=1;
    tail=0;
    for(int i=1;i<=n;i++){
        //head<=tail保证队列中已有数字，如果队尾数字大于等于v[i]，则删除
        //因为这里是维护最小值数组的，所以比新来的数字大的都没用了
        while(head<=tail && que[tail]>=v[i]){
            tail--;
        }
        //v[i]加入队列
        que[++tail]=v[i];
        //记录进入元素的下标
        pos[tail]=i;
        //printf("头 %d 尾 %d\n",head,tail);
        //printf("队列:\n");
        // for(int i=head;i<=tail;i++){
        //     printf("%d ",que[i]);
        // }
        // printf("\n");
        //索引太老的出队
        if(pos[head]<i-k+1){
            //printf("%d出队\n",que[head]);
            head++;
        }
        //索引i大于等于k才有满足的答案
        if(i>=k){
            //这里的i就是窗口区间的最右端
            //就等于当前队列的队头元素，最小值
            ans_min[i]=que[head];
            //printf("加入答案 %d %d\n",i,ans_min[i]);
        }
    }
    for(int i=k;i<=n;i++){
        printf("%d%c",ans_min[i],(i==n?'\n':' '));
    }
}
void get_max(){
    head=1;
    tail=0;
    for(int i=1;i<=n;i++){
        while(head<=tail && que[tail]<=v[i]){
            tail--;
        }
        que[++tail]=v[i];
        pos[tail]=i;
        if(pos[head]<i-k+1){
            head++;
        }
        if(i>=k){
            ans_max[i]=que[head];
        }
    }
    for(int i=k;i<=n;i++){
        printf("%d%c",ans_max[i],(i==n?'\n':' '));
    }
}
int main(void){
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++){
        scanf("%d",&v[i]);
    }
    get_min();
    get_max();
    return 0;
}